package com.example.mcp;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.Build;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 网络连通性检测工具。
 *
 * 功能：
 * 1) 判断设备是否有可用的本地网络（Wi‑Fi/蜂窝/以太网）
 * 2) 通过访问多个公共探测地址（返回 204/200）验证外网连通性
 * 3) 提供同步与异步两种检测方式
 */
public class NetworkChecker {

    /**
     * 用于外网连通性检测的探测地址（任一成功即视为可达）。
     * 根据地区可调整顺序或替换为更稳定的站点。
     */
    private static final List<String> DEFAULT_PROBE_URLS = Arrays.asList(
            "https://www.google.com/generate_204",
            "https://connectivitycheck.gstatic.com/generate_204",
            "https://www.baidu.com",
            "https://www.qq.com"
    );

    private static final int DEFAULT_TIMEOUT_MS = 2500;

    private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();

    public interface Callback {
        void onResult(Result result);
    }

    public static final class Result {
        public final boolean localNetworkAvailable;
        public final boolean internetReachable;
        public final String reachableEndpoint;
        public final Exception error;

        public Result(boolean localNetworkAvailable, boolean internetReachable, String reachableEndpoint, Exception error) {
            this.localNetworkAvailable = localNetworkAvailable;
            this.internetReachable = internetReachable;
            this.reachableEndpoint = reachableEndpoint;
            this.error = error;
        }

        @Override
        public String toString() {
            return "Result{" +
                    "localNetworkAvailable=" + localNetworkAvailable +
                    ", internetReachable=" + internetReachable +
                    ", reachableEndpoint='" + reachableEndpoint + '\'' +
                    ", error=" + (error != null ? error.getMessage() : "null") +
                    '}';
        }
    }

    /**
     * 检查是否存在可用的本地网络（不代表可访问外网）。
     */
    public static boolean isLocalNetworkAvailable(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            return false;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network activeNetwork = cm.getActiveNetwork();
            if (activeNetwork == null) {
                return false;
            }
            NetworkCapabilities caps = cm.getNetworkCapabilities(activeNetwork);
            return caps != null && (
                    caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                            caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                            caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
                            caps.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)
            );
        } else {
            android.net.NetworkInfo info = cm.getActiveNetworkInfo();
            return info != null && info.isConnected();
        }
    }

    /**
     * 同步检测外网连通性（请勿在主线程调用）。
     * 返回可达即 true；会尝试多个探测地址，任一成功即判定可达。
     */
    public static boolean canReachInternet() {
        return canReachInternet(DEFAULT_PROBE_URLS, DEFAULT_TIMEOUT_MS) != null;
    }

    /**
     * 同步检测外网连通性并返回可达的探测地址（若全部失败返回 null）。
     */
    public static String canReachInternet(List<String> probeUrls, int timeoutMs) {
        for (String url : probeUrls) {
            if (probeOnce(url, timeoutMs)) {
                return url;
            }
        }
        return null;
    }

    /**
     * 异步综合检测（本地网络 + 外网连通性）。
     * 注意：可能回调在后台线程，如需更新 UI 请自行切换到主线程。
     */
    public static void checkAsync(Context context, Callback callback) {
        EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                boolean local = false;
                String reachable = null;
                Exception error = null;
                try {
                    local = isLocalNetworkAvailable(context);
                    if (local) {
                        reachable = canReachInternet(DEFAULT_PROBE_URLS, DEFAULT_TIMEOUT_MS);
                    }
                } catch (Exception e) {
                    error = e;
                }
                boolean internet = reachable != null;
                Result result = new Result(local, internet, reachable, error);
                if (callback != null) {
                    callback.onResult(result);
                }
            }
        });
    }

    /**
     * 尝试访问单个探测地址。
     */
    private static boolean probeOnce(String urlString, int timeoutMs) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(urlString);
            conn = (HttpURLConnection) url.openConnection();
            conn.setInstanceFollowRedirects(false);
            conn.setConnectTimeout(timeoutMs);
            conn.setReadTimeout(timeoutMs);
            conn.setUseCaches(false);
            conn.setRequestMethod("GET");
            conn.setRequestProperty("User-Agent", "NetworkChecker/1.0 (Android)");
            conn.setRequestProperty("Connection", "close");
            int code = conn.getResponseCode();
            // 一些探测点返回 204，无内容；也接受 200 作为可达
            return code == HttpURLConnection.HTTP_NO_CONTENT || code == HttpURLConnection.HTTP_OK;
        } catch (IOException ignored) {
            return false;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }
}


